﻿using GameFramework;
using GameFramework.Event;
using System.Collections.Generic;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

namespace GFTest
{
    public class ProcedurePreload : ProcedureBase
    {
        private Dictionary<string, bool> m_LoadedFlag = new Dictionary<string, bool>();

        public override bool UseNativeDialog
        {
            get
            {
                return true;
            }
        }

        protected override void OnEnter(ProcedureOwner procedureOwner)
        {
            base.OnEnter(procedureOwner);
            GameEntry.Event.Subscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
            GameEntry.Event.Subscribe(LoadLuaScriptSuccessEventArgs.EventId, OnLoadLuaScriptSuccess);
            GameEntry.Event.Subscribe(LoadLuaScriptFailureEventArgs.EventId, OnLoadLuaScriptFailure);
            GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
            GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);

            m_LoadedFlag.Clear();
            PreloadResources();
        }

        protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown)
        {
            GameEntry.Event.Unsubscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
            GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
            GameEntry.Event.Unsubscribe(LoadLuaScriptSuccessEventArgs.EventId, OnLoadLuaScriptSuccess);
            GameEntry.Event.Unsubscribe(LoadLuaScriptFailureEventArgs.EventId, OnLoadLuaScriptFailure);
            GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
            GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
            GameEntry.Lua.StartVM();

            base.OnLeave(procedureOwner, isShutdown);
        }

        private void PreloadResources()
        {
            LoadDataTable("UIForm");

            LoadLuaScript("LuaMain");
            LoadLuaScript("LuaEntry");
            LoadLuaScript("LuaConfig");

            LoadLuaScript("Utility/Alias");
            LoadLuaScript("Utility/Enum");
            LoadLuaScript("Utility/InitUtility");
            LoadLuaScript("Utility/Functions");

            LoadLuaScript("LuaObject/LuaObject");
            LoadLuaScript("LuaObject/LuaObjectPool");
            LoadLuaScript("LuaObject/LuaNGUIForm");
            LoadLuaScript("UI/LuaNGUIFormFactory");
            LoadLuaScript("UI/GTWindowForm");


            LoadLuaScript("Procedure/ProcedureMain");
        }

        private void LoadConfig(string configName)
        {
            m_LoadedFlag.Add(string.Format("Config.{0}", configName), false);
            GameEntry.Config.LoadConfig(configName, this);
        }

        private void LoadDataTable(string dataTableName)
        {
            m_LoadedFlag.Add(string.Format("DataTable.{0}", dataTableName), false);
            GameEntry.DataTable.LoadDataTable(dataTableName, this);
        }

        private void LoadDictionary(string dictionaryName)
        {
            m_LoadedFlag.Add(string.Format("Dictionary.{0}", dictionaryName), false);
            GameEntry.Localization.LoadDictionary(dictionaryName, this);
        }

        private void LoadLuaScript(string luaScriptName)
        {
            m_LoadedFlag.Add(string.Format("LuaScript.{0}", luaScriptName), false);
            GameEntry.Lua.LoadScript(luaScriptName, this);
        }

        // Use this for initialization
        void Start()
        {

        }

        // Update is called once per frame
        protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

            IEnumerator<bool> iter = m_LoadedFlag.Values.GetEnumerator();
            while (iter.MoveNext())
            {
                if (!iter.Current)
                {
                    return;
                }
            }

            ChangeState<ProcedureMain>(procedureOwner);
        }


        private void OnLoadConfigSuccess(object sender, GameEventArgs e)
        {
            LoadConfigSuccessEventArgs ne = (LoadConfigSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadedFlag[string.Format("Config.{0}", ne.ConfigName)] = true;
            Log.Info("Load config '{0}' OK.", ne.ConfigName);
        }

        private void OnLoadConfigFailure(object sender, GameEventArgs e)
        {
            LoadConfigFailureEventArgs ne = (LoadConfigFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Can not load config '{0}' from '{1}' with error message '{2}'.", ne.ConfigName, ne.ConfigAssetName, ne.ErrorMessage);
        }

        private void OnLoadLuaScriptSuccess(object sender, GameEventArgs e)
        {
            LoadLuaScriptSuccessEventArgs ne = (LoadLuaScriptSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadedFlag[string.Format("LuaScript.{0}", ne.LuaScriptName)] = true;
            Log.Info("Load lua script '{0}' OK.", ne.LuaScriptName);
        }

        private void OnLoadLuaScriptFailure(object sender, GameEventArgs e)
        {
            LoadLuaScriptFailureEventArgs ne = (LoadLuaScriptFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Can not load lua script '{0}' from '{1}' with error message '{2}'.", ne.LuaScriptName, ne.LuaScriptAssetName, ne.ErrorMessage);
        }

        private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
        {
            LoadDataTableSuccessEventArgs ne = (LoadDataTableSuccessEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            m_LoadedFlag[string.Format("DataTable.{0}", ne.DataTableName)] = true;
            Log.Info("Load data table '{0}' OK.", ne.DataTableName);
        }

        private void OnLoadDataTableFailure(object sender, GameEventArgs e)
        {
            LoadDataTableFailureEventArgs ne = (LoadDataTableFailureEventArgs)e;
            if (ne.UserData != this)
            {
                return;
            }

            Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableName, ne.DataTableAssetName, ne.ErrorMessage);
        }
    }
}
